package com.longcai.cm.base.shiro;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.longcai.cm.moudules.system.dao.SysUsersMapper;
import com.longcai.cm.moudules.system.domain.*;
import com.longcai.cm.moudules.system.service.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.mgt.RealmSecurityManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.crazycake.shiro.RedisSessionDAO;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author chenyue
 */
public class MyShiroRealm extends AuthorizingRealm {


    @Resource
    private SysUsersMapper sysUsersMapper;

    @Resource
    private RedisSessionDAO redisSessionDAO;

    @Resource
    private SysUserRolesService sysUserRolesService;

    @Resource
    private SysRolesService sysRolesService;

    @Resource
    private SysRoleMenusService sysRoleMenusService;

    @Resource
    private SysMenusService sysMenusService;


    private SysUsers selectByUsername(String username) {

        QueryWrapper<SysUsers> wrapper = new QueryWrapper<>();
        wrapper.eq("username", username);
        List<SysUsers> sysUsersList = sysUsersMapper.selectList(wrapper);
        if (sysUsersList.size() > 0) {
            return sysUsersList.get(0);
        }
        return null;
    }

    /**
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //获取用户的输入的账号.
        String password = new String((char[]) token.getCredentials());
        String username = (String) token.getPrincipal();

        SysUsers sysUsers = selectByUsername(username);

        if (sysUsers == null) {
            throw new UnknownAccountException("账号或密码不正确");
        }
        // 密码错误
        if (!password.equals(sysUsers.getPassword())) {
            throw new IncorrectCredentialsException("账号或密码不正确");
        }
        // 账号停用校验
        if ("1".equals(sysUsers.getState())) {
            throw new LockedAccountException("账号已被锁定,请联系管理员");
        }

        Map<String, Object> map = JSON.parseObject(JSON.toJSONString(sysUsers));
        map.put("userType", "systemUser");

        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo
                (map, sysUsers.getPassword(), getName());
        // 当验证都通过后，把用户信息放在session里
        Session session = SecurityUtils.getSubject().getSession();
        session.setAttribute("userSession", sysUsers);
        session.setAttribute("userSessionId", sysUsers.getId());
        return authenticationInfo;
    }


    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("用户权限配置。。。。。。。。。。");
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        System.out.println(principalCollection.getPrimaryPrincipal());
        SysUsers sysUsers = JSON.parseObject(principalCollection.getPrimaryPrincipal().toString(), SysUsers.class);
        SysUsersRole sysUsersRole = sysUserRolesService.lambdaQuery().eq(SysUsersRole::getUserId, sysUsers.getId()).one();
        SysRoles role = sysRolesService.getById(sysUsersRole.getRoleId());
        if (StringUtils.isNotBlank(role.getRoleName())) {
            info.addRole(role.getRoleName());
        }
        List<SysRoleMenus> menusList = sysRoleMenusService.lambdaQuery().eq(SysRoleMenus::getRoleId, role.getId()).list();
        for (SysRoleMenus roleMenu : menusList) {
            SysMenus menu = sysMenusService.getById(roleMenu.getMenuId());
            if (menu != null) {
                if (StringUtils.isNotBlank(menu.getPermission())) {
                    info.addStringPermission(menu.getPermission());
                }
            }
        }
        return info;
    }

    /**
     * 根据userId 清除当前session存在的用户的权限缓存
     *
     * @param userIds 已经修改了权限的userId
     */
    public void clearUserAuthByUserId(List<String> userIds) {
        if (null == userIds || userIds.isEmpty()) {
            return;
        }
        //获	取所有session
        Collection<Session> sessions = redisSessionDAO.getActiveSessions();
        //定义返回
        List<SimplePrincipalCollection> list = new ArrayList<>();
        for (Session session : sessions) {
            //获取session登录信息。
            Object obj = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
            if (obj instanceof SimplePrincipalCollection) {
                //强转
                SimplePrincipalCollection spc = (SimplePrincipalCollection) obj;
                //判断用户，匹配用户ID。
                obj = spc.getPrimaryPrincipal();
                if (obj instanceof SysUsers) {
                    SysUsers sysUsers = (SysUsers) obj;
                    System.out.println("SysUsers:" + sysUsers);
                    //比较用户ID，符合即加入集合
                    if (userIds.contains(sysUsers.getId())) {
                        list.add(spc);
                    }
                }
            }
        }

        RealmSecurityManager securityManager = (RealmSecurityManager) SecurityUtils.getSecurityManager();
        MyShiroRealm realm = (MyShiroRealm) securityManager.getRealms().iterator().next();
        for (SimplePrincipalCollection simplePrincipalCollection : list) {
            realm.clearCachedAuthorizationInfo(simplePrincipalCollection);
        }


    }

    @Override
    public boolean supports(AuthenticationToken authenticationToken) {
        //设置此Realm支持的Token
        return (authenticationToken instanceof UsernamePasswordToken);
    }


}
